package com.library.management.entity;

import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 图书分类实体类
 * 管理图书分类体系，支持多级分类结构
 *
 * 关联关系：
 * - 自关联：父分类和子分类
 * - 一对多：分类下的图书
 *
 * 业务功能：
 * - 分类树形结构管理
 * - 图书分类组织
 * - 分类排序和展示
 *
 * @author 开发者
 * @version 1.0
 * @since 2025-10-19
 */
@Entity
@Table(name = "book_categories", indexes = {
        @Index(name = "idx_categories_code", columnList = "category_code"),
        @Index(name = "idx_categories_parent", columnList = "parent_id"),
        @Index(name = "idx_categories_sort", columnList = "sort_order")
})
@Data
@EqualsAndHashCode(exclude = {"parent", "children", "books"})
@ToString(exclude = {"parent", "children", "books"})
public class BookCategory {

    // ========== 主键标识 ==========

    /**
     * 分类ID - 主键，自增长
     * 数据库字段：id (BIGINT, PRIMARY KEY, AUTO_INCREMENT)
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // ========== 分类基本信息 ==========

    /**
     * 分类编码 - 唯一分类标识，用于程序识别
     * 数据库字段：category_code (VARCHAR(20), UNIQUE, NOT NULL)
     */
    @Column(name = "category_code", unique = true, nullable = false, length = 20)
    private String categoryCode;

    /**
     * 分类名称 - 分类显示名称
     * 数据库字段：category_name (VARCHAR(50), NOT NULL)
     */
    @Column(name = "category_name", nullable = false, length = 50)
    private String categoryName;

    // ========== 树形结构关联关系 ==========

    /**
     * 父分类 - 上级分类，支持多级分类结构
     * 多对一关系，自关联，外键关联自身表
     * 延迟加载提高性能
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id", foreignKey = @ForeignKey(name = "fk_categories_parent_id"))
    private BookCategory parent;

    /**
     * 子分类列表 - 下级分类列表
     * 一对多关系，级联操作：所有操作
     * 延迟加载提高性能
     */
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<BookCategory> children = new ArrayList<>();

    // ========== 图书关联关系 ==========

    /**
     * 图书列表 - 该分类下的所有图书
     * 一对多关系，级联操作：所有操作
     * 延迟加载提高性能
     */
    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Book> books = new ArrayList<>();

    // ========== 分类描述信息 ==========

    /**
     * 分类描述 - 分类详细说明
     * 数据库字段：description (TEXT)
     */
    @Column(columnDefinition = "TEXT")
    private String description;

    /**
     * 排序字段 - 控制分类显示顺序，数值越小越靠前
     * 数据库字段：sort_order (INT), DEFAULT 0
     */
    @Column(name = "sort_order")
    private Integer sortOrder = 0;

    // ========== 审计字段 ==========

    /**
     * 创建人ID - 记录创建者
     * 数据库字段：created_by (BIGINT)
     */
    @Column(name = "created_by")
    private Long createdBy;

    /**
     * 更新人ID - 记录最后修改者
     * 数据库字段：updated_by (BIGINT)
     */
    @Column(name = "updated_by")
    private Long updatedBy;

    /**
     * 创建时间 - 记录创建时间，自动生成
     * 数据库字段：created_time (DATETIME), DEFAULT CURRENT_TIMESTAMP
     */
    @CreationTimestamp
    @Column(name = "created_time", updatable = false)
    private LocalDateTime createdTime;

    /**
     * 更新时间 - 记录最后修改时间，自动更新
     * 数据库字段：updated_time (DATETIME), DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
     */
    @UpdateTimestamp
    @Column(name = "updated_time")
    private LocalDateTime updatedTime;

    // ========== 业务方法 ==========

    /**
     * 检查是否为根分类
     * 根分类没有父分类
     *
     * @return true-是根分类，false-不是根分类
     */
    public boolean isRootCategory() {
        return this.parent == null;
    }

    /**
     * 检查是否为叶子分类
     * 叶子分类没有子分类
     *
     * @return true-是叶子分类，false-不是叶子分类
     */
    public boolean isLeafCategory() {
        return this.children == null || this.children.isEmpty();
    }

    /**
     * 获取完整分类路径
     * 生成从根分类到当前分类的完整路径
     *
     * @return 完整分类路径字符串
     */
    public String getFullPath() {
        if (this.parent == null) {
            return this.categoryName;
        }
        return this.parent.getFullPath() + " > " + this.categoryName;
    }

    /**
     * 获取分类层级深度
     * 计算分类在树形结构中的深度，根分类深度为1
     *
     * @return 分类层级深度
     */
    public int getDepth() {
        if (this.parent == null) {
            return 1;
        }
        return this.parent.getDepth() + 1;
    }

    /**
     * 获取该分类下的图书数量
     *
     * @return 图书数量
     */
    public int getBookCount() {
        return this.books != null ? this.books.size() : 0;
    }

    /**
     * 获取该分类及其所有子分类下的图书数量
     * 递归统计所有子分类的图书数量
     *
     * @return 总图书数量
     */
    public int getTotalBookCount() {
        int count = getBookCount();
        if (this.children != null) {
            for (BookCategory child : this.children) {
                count += child.getTotalBookCount();
            }
        }
        return count;
    }
}